'use strict';

/**
 * 用户服务
 */
const Service = require('egg').Service;
const PasswordUtil = require('../utils/password');

class UserService extends Service {
  /**
   * 创建用户
   * @param {Object} userData - 用户数据
   * @return {Promise<Object>} 创建的用户
   */
  async create(userData) {
    const { ctx } = this;
    // 密码加密
    userData.password = await PasswordUtil.hash(userData.password);
    return ctx.model.User.create(userData);
  }

  /**
   * 查询用户列表
   * @param {Object} query - 查询条件
   * @param {Number} page - 页码
   * @param {Number} pageSize - 每页数量
   * @return {Promise<Object>} 用户列表和总数
   */
  async list(query = {}, page = 1, pageSize = 10) {
    const { ctx } = this;
    // 确保分页参数是数字类型
    const pageNum = parseInt(page) || 1;
    const pageSizeNum = parseInt(pageSize) || 10;
    const offset = (pageNum - 1) * pageSizeNum;
    const where = {};

    if (query.username) {
      where.username = { [ctx.app.Sequelize.Op.like]: `%${query.username}%` };
    }

    if (query.status !== undefined && query.status !== '') {
      where.status = query.status;
    }

    if (query.departmentId) {
      where.departmentId = query.departmentId;
    }

    const { count, rows } = await ctx.model.User.findAndCountAll({
      where,
      offset,
      limit: pageSizeNum,
      order: [['create_time', 'DESC']],
      attributes: { exclude: ['password'] }, // 排除密码字段
      include: [
        { model: ctx.model.Department, as: 'department', attributes: ['id', 'name'] },
        { model: ctx.model.Role, as: 'roles', attributes: ['id', 'name'], through: { attributes: [] } },
      ],
    });

    return {
      list: rows,
      total: count,
      page: pageNum,
      pageSize: pageSizeNum,
    };
  }

  /**
   * 查询单个用户
   * @param {string} id - 用户ID
   * @return {Promise<Object>} 用户信息
   */
  async findById(id) {
    const { ctx } = this;
    return ctx.model.User.findByPk(id, {
      attributes: { exclude: ['password'] }, // 排除密码字段
      include: [
        { model: ctx.model.Department, as: 'department', attributes: ['id', 'name'] },
        { model: ctx.model.Role, as: 'roles', attributes: ['id', 'name', 'code'], through: { attributes: [] } },
      ],
    });
  }

  /**
   * 更新用户
   * @param {string} id - 用户ID
   * @param {Object} userData - 更新的用户数据
   * @return {Promise<Object>} 更新后的用户
   */
  async update(id, userData) {
    const { ctx } = this;
    const user = await this.findById(id);
    if (!user) {
      ctx.throw(404, '用户不存在');
    }

    // 如果更新密码，则加密
    if (userData.password) {
      userData.password = await PasswordUtil.hash(userData.password);
    }

    return user.update(userData);
  }

  /**
   * 删除用户
   * @param {string} id - 用户ID
   * @return {Promise<Boolean>} 是否删除成功
   */
  async destroy(id) {
    const { ctx } = this;
    const user = await this.findById(id);
    if (!user) {
      ctx.throw(404, '用户不存在');
    }

    return user.destroy();
  }

  /**
   * 批量删除用户
   * @param {Array} ids - 用户ID数组
   * @return {Promise<Number>} 删除的数量
   */
  async batchDestroy(ids) {
    const { ctx } = this;
    return ctx.model.User.destroy({
      where: { id: ids },
    });
  }

  /**
   * 重置密码
   * @param {string} id - 用户ID
   * @param {string} newPassword - 新密码
   * @return {Promise<Object>} 更新后的用户
   */
  async resetPassword(id, newPassword) {
    const { ctx } = this;
    const user = await this.findById(id);
    if (!user) {
      ctx.throw(404, '用户不存在');
    }

    user.password = await PasswordUtil.hash(newPassword);
    return user.save();
  }

  /**
   * 更新用户状态
   * @param {string} id - 用户ID
   * @param {boolean} status - 状态
   * @return {Promise<Object>} 更新后的用户
   */
  async updateStatus(id, status) {
    const { ctx } = this;
    const user = await this.findById(id);
    if (!user) {
      ctx.throw(404, '用户不存在');
    }

    user.status = status;
    return user.save();
  }


  /**
   * 用户登录
   * @param {Object} loginData - 登录数据
   * @return {Promise<Object>} 用户信息和token
   */
  async login(loginData) {
    const { ctx } = this;
    const { username, password } = loginData;

    // 查询用户
    const user = await ctx.model.User.findOne({
      where: { username },
      include: [
        { model: ctx.model.Role, as: 'roles', attributes: ['id', 'name', 'code'], through: { attributes: [] } },
      ],
    });

    if (!user) {
      ctx.throw(401, '用户名或密码错误');
    }

    // 验证密码
    const isPasswordValid = await PasswordUtil.compare(password, user.password);
    if (!isPasswordValid) {
      ctx.throw(401, '用户名或密码错误');
    }

    // 检查用户状态
    if (!user.status) {
      ctx.throw(401, '用户已禁用');
    }

    // 更新最后登录时间（使用update_time字段）
    user.updateTime = new Date();
    await user.save();

    // 生成token
    const token = ctx.app.jwt.sign({
      id: user.id,
      username: user.username,
      realName: user.realName,
      roles: user.roles.map(role => role.name),
    }, ctx.app.config.jwt.secret, {
      expiresIn: ctx.app.config.jwt.expiresIn,
    });

    return {
      user: {
        id: user.id,
        username: user.username,
        realName: user.realName,
        email: user.email,
        phone: user.phone,
        avatar: user.avatar,
        status: user.status,
        departmentId: user.departmentId,
        roles: user.roles,
      },
      token,
    };
  }

  /**
   * 用户登出
   * @param {string} userId - 用户ID
   * @return {Promise<void>}
   */
  async logout(userId) {
    // 登出逻辑可以根据需求实现，例如记录登出时间、清除token等
    // 这里我们简单实现
    const { ctx } = this;
    const user = await this.findById(userId);
    if (!user) {
      ctx.throw(404, '用户不存在');
    }

    // 可以在这里添加登出日志等操作
    return;
  }

  /**
   * 修改密码
   * @param {string} userId - 用户ID
   * @param {Object} passwordData - 密码数据
   * @return {Promise<Object>} 更新后的用户
   */
  async changePassword(userId, passwordData) {
    const { ctx } = this;
    const { oldPassword, newPassword } = passwordData;

    // 直接查询用户，包含密码字段
    const user = await ctx.model.User.findByPk(userId.toString());
    if (!user) {
      ctx.throw(404, '用户不存在');
    }

    // 验证旧密码
    const isPasswordValid = await PasswordUtil.compare(oldPassword, user.password);
    if (!isPasswordValid) {
      ctx.throw(400, '旧密码错误');
    }

    // 设置新密码
    user.password = await PasswordUtil.hash(newPassword);
    return user.save();
  }
}
module.exports = UserService;
